package com.shop.cereshop.app.controller.tencent.im;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.shop.cereshop.app.tencent.im.callback.TimCallbackHandlerFactory;
import com.shop.cereshop.commons.domain.im.tx.req.ImBaseModel;
import com.shop.cereshop.commons.tencent.im.model.callback.response.CallbackResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * @description: 腾讯IM 消息的回调拦截
 * @author zdd
 * @date 2025/9/8 14:11
 * @version 1.0
 */
@RestController
@RequestMapping("/tim/callback")
@Slf4j(topic = "TimCallbackController")
@Api(value = "腾讯IM 消息的回调拦截", tags = "腾讯IM 消息的回调拦截")
public class TimCallbackController {

    @Resource
    private ImBaseModel imBaseModel;

    @Autowired
    private TimCallbackHandlerFactory handlerFactory;


    @ApiOperation(value = "腾讯IM消息统一的回调入口")
    @PostMapping
    public ResponseEntity<CallbackResponse> handleCallback(HttpServletRequest request) {
        long startTime = System.currentTimeMillis();

        // 从URL参数中提取必要信息
        String sdkAppid = request.getParameter("SdkAppid");
        String callbackCommand = request.getParameter("CallbackCommand");
        String contentType = request.getParameter("contenttype");
        String clientIp = request.getParameter("ClientIP");
        String optPlatform = request.getParameter("OptPlatform");

        log.info("Received callback - SdkAppid: {}, CallbackCommand: {}, ClientIP: {}, OptPlatform: {}",
                sdkAppid, callbackCommand, clientIp, optPlatform);

        // 基础校验
        if (StringUtils.isBlank(sdkAppid)) {
            log.warn("Missing required parameter: SdkAppid");
            return ResponseEntity.badRequest().body(CallbackResponse.error("Missing SdkAppid"));
        }

        if (StringUtils.isBlank(callbackCommand)) {
            log.warn("Missing required parameter: CallbackCommand");
            return ResponseEntity.badRequest().body(CallbackResponse.error("Missing CallbackCommand"));
        }

        // 校验 SDKAppID (安全考虑)
        try {
            if (!imBaseModel.getSdkAppId().equals(Integer.valueOf(sdkAppid))) {
                log.warn("Invalid SdkAppid: {}", sdkAppid);
                return ResponseEntity.status(HttpStatus.FORBIDDEN).body(CallbackResponse.error("Invalid SdkAppid"));
            }
        } catch (NumberFormatException e) {
            log.warn("SdkAppid format error: {}", sdkAppid);
            return ResponseEntity.status(HttpStatus.FORBIDDEN).body(CallbackResponse.error("Invalid SdkAppid"));
        }

        // 4. 尝试读取并解析请求 Body (JSON)
        String requestBody;
        try {
            requestBody = request.getReader().lines().reduce("", (accumulator, actual) -> accumulator + actual);
            log.info("Request Body: {}", requestBody);
        } catch (Exception e) {
            log.error("Failed to read request body", e);
            return ResponseEntity.badRequest().body(CallbackResponse.error("Failed to read request body: " + e.getMessage()));
        }

        if (StringUtils.isBlank(requestBody)) {
            log.warn("Request body is empty");
            return ResponseEntity.badRequest().body(CallbackResponse.error("Request body is empty"));
        }

        // 5. 使用工厂处理回调请求
        CallbackResponse response;
        try {
            response = handlerFactory.handle(callbackCommand, requestBody, sdkAppid, contentType, clientIp, optPlatform);
        } catch (IllegalArgumentException e) {
            log.warn("Unsupported CallbackCommand: {}", callbackCommand);
            return ResponseEntity.badRequest().body(CallbackResponse.error(e.getMessage()));
        } catch (JsonProcessingException e) {
            log.error("Failed to parse request body for command: " + callbackCommand, e);
            return ResponseEntity.badRequest().body(CallbackResponse.error("Failed to parse request: " + e.getMessage()));
        } catch (Exception e) {
            log.error("Error processing callback for command: " + callbackCommand, e);
            CallbackResponse callbackResponse = CallbackResponse.error("Internal server error during processing: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(callbackResponse);
        }

        long endTime = System.currentTimeMillis();
        log.info("Callback processing completed. Command: {}, Duration: {}ms, Response: {}",
                callbackCommand, (endTime - startTime), response);

        // 返回响应
        // 腾讯云 IM 期望的是 JSON 格式的响应体，HTTP 状态码 200 通常即可
        // 即使业务处理失败，也建议返回 200 OK，但 ErrorCode 为 1，让腾讯云 IM 知道是业务失败
        // 这样可以避免腾讯云 IM 因为 HTTP 500 而进行不必要的重试
        return ResponseEntity.ok(response);
    }


}
